home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
m2
/
cat3src
/
cat
/
msglist.i
< prev
next >
Wrap
Text File
|
1997-10-26
|
62KB
|
1,775 lines
IMPLEMENTATION MODULE msgList;
(*$Z+*)
(*==============================================================*
* Modul: CAT-Anzeigemodul fr Stichwortlisten *
* Autor: Dirk Steins *
* erstellt am: 25.07.1992 *
* letzte nderung am: 27.10.1994 *
* Version: 0.1 *
* Interne Version: V#0001 *
*==============================================================*
*----------------------------------------------------------------------------
* Datum Vers. Autor nderung (Arbeitsbericht)
*----------------------------------------------------------------------------
* 25.07.92 0.1 DS Erste Implementation erstellt
* 27.07.92 0.2 DS Erweiterungen um weitere Spalten in Anzeige und
* kleine Bugfixes
*----------------------------------------------------------------------------
*)
(*-- MM2-Module ------------------------------------------------------------*)
FROM SYSTEM IMPORT ADDRESS, ADR, TSIZE, CALLSYS, CADR;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;
IMPORT Lists;
IMPORT GrafBase;
IMPORT BinOps;
IMPORT Strings;
IMPORT StrConv;
IMPORT MOSGlobals;
IMPORT Keyboard;
IMPORT Block;
FROM Keyboard IMPORT SpecialCode;
(*-- Cat-Module ------------------------------------------------------------*)
FROM Void IMPORT v;
FROM UserInformation IMPORT UserBLK;
IMPORT data;
IMPORT dataSys;
IMPORT EditTypes;
IMPORT MTE;
IMPORT VDIStandards;
IMPORT MausTauschrsc;
IMPORT CatTypes;
IMPORT handlePool;
IMPORT ConfVars;
IMPORT WdwManager;
IMPORT RectFuncs;
IMPORT FontSelect;
IMPORT CatGlobal;
IMPORT CatFiles;
IMPORT grin;
IMPORT grinTools;
IMPORT Varnames;
IMPORT QuickSort;
IMPORT ZSearchDial;
IMPORT GroupSelect;
IMPORT Clip;
IMPORT SearchHelp;
IMPORT AssFuncs;
IMPORT ConvertDate;
IMPORT UUDecode;
IMPORT Protokoll;
(*-- Magic-Lib -------------------------------------------------------------*)
IMPORT MagicStrings;
IMPORT MagicAES;
IMPORT MagicVDI;
IMPORT MagicFSM;
IMPORT MagicDOS;
IMPORT MagicConvert;
(*-- Magic-Tools -----------------------------------------------------------*)
IMPORT mtAppl;
IMPORT mtArea;
IMPORT mtUtils;
IMPORT mtAlerts;
IMPORT mtDials;
IMPORT mtPopups;
IMPORT mtTextfiles;
IMPORT mtXobjects;
FROM MsgListBase IMPORT
maxParts, partFormatLength, Selected, inTree, notRead, doRedraw, firstRead, initRead,
lEntry, listEntry , lineDist, pixOffset, privateParts , globalParts,
ownEff, quoteEff, lastSaveMode , extendedCommentMode, butBox, selPop,
removePop, sortPop, listEntryPtr, listArray, listArrayPtr,
partNameType, partFormat, partType, partArrayType, partArrayDesc,
listWindow, listWdwPtr, sortType, globalNumber,
windows, FindNum, ClearNum, FindWinCond, FindHandleCond,
FindGroupCond, findMsgIdx, FindNextSelected, FindPrevSelected,
FindNextDeselected, FindPrevDeselected, listNextMess,
hasSelectedEntries, countSelectedEntries, toggleBit, redrawEntry,
toggleEntry, invertSelection, deselectEntries, deselectReadEntries,
drawCursor, ShowCursor, AdjustTreePos, GetLinePart, shrinkToEnd,
shrinkList, showAll, selectTree, selectFromTop, removeTree,
listSelectFiltered, openSelected, freeList, doSort, doMark,
redrawButton, careForSelected, drawListWdw,
checkPopups, handleButtons, clickInListWindow, handleListTimer,
handleListKey, getListScroll, closeListWindow, topListWdw,
untopListWdw, updateListWdw, hideListWdw, setListWork, snapListWdw,
listGetSelectedSize, listGetSelectedData, listGetHeader,
listReadData, MakeTitle;
CONST LF = 12C;
CR = 15C;
(* ---------------------- Font-Funktionen ----------------------- *)
PROCEDURE iListSetFont (wdw : INTEGER; fnt, fntSize : INTEGER; redraw: BOOLEAN);
(* Setzt den Font fr das Stichwortlistenfenster *)
VAR r : GrafBase.Rectangle;
ptr : listWdwPtr;
varName : CatTypes.String255;
BEGIN
IF handlePool.FindEntry (ADR(wdw), FindWinCond, windows, ptr)
THEN
WITH ptr^ DO
font := fnt;
fontSize := fntSize;
FontSelect.SetFont (vdi, font, fontSize, TRUE, monoSpaced, isFSM, charWidth, charHeight);
maxWidth := partArray.width * charWidth;
(* Jetzt ist der Font gesetzt. Jetzt noch Window snappen und dann neu
* zeichnen lassen
*)
Strings.Concat (cListFont, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, font);
Strings.Concat (cListSize, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, fontSize);
WdwManager.SetDocumentParms (wdw, 1, charHeight+lineDist);
WdwManager.GetWdwSize (wdw, r);
WdwManager.SetWdwSize (wdw, r);
r := listWork;
INC (r.x, pixOffset);
IF redraw THEN WdwManager.RedrawWdw (wdw, r); END;
END; (* WITH ed^ DO *)
END;
END iListSetFont;
(*-------------- exportierte Funktionen -----------------------*)
PROCEDURE listRemoveTree (hdl: LONGCARD; grinWdw: INTEGER;
msgNum : CARDINAL; setReadFlag: BOOLEAN);
(* Entfernt den Baum mit der Nachricht msgNum aus der Liste im Fenster
* wdw, falls das grinWdw bereinstimmt
*)
VAR ptr: listWdwPtr;
idx: CARDINAL;
(*$H+*)
PROCEDURE unselTree (handle: data.OneGroupHandle;
msgIdx: CARDINAL;
mess : dataSys.pBlockPtr);
VAR i : CARDINAL;
BEGIN
(* search for mess *)
WITH ptr^ DO
IF setReadFlag
THEN
INCL (mess^.bits, dataSys.bGelesen);
data.SetBits (handle, msgIdx, mess^.bits);
END;
(* First try normal list *)
IF (msgIdx <= maxPos) & (list^[msgIdx].msgNum = msgIdx)
THEN
i := msgIdx;
ELSE
(* Not found, search from end *)
i := maxPos;
WHILE (list^[i].msgNum # msgIdx) & (i > 0) DO DEC (i) END;
END;
IF list^[i].msgNum = msgIdx
THEN
EXCL (list^[i].flags, Selected);
EXCL (list^[i].flags, inTree);
END;
END;
END unselTree;
BEGIN
IF handlePool.FindEntry(ADR(hdl), FindHandleCond, windows, ptr)
THEN
IF grinWdw # ptr^.grinWindow
THEN
RETURN
END;
WITH ptr^ DO
findMsgIdx (ptr, msgNum, idx);
IF idx < dataSys.notSaved
THEN
(* Erstmal Baum deselektieren *)
data.WalkTree (grHandle^.Zugriff, msgNum, TRUE, unselTree);
(* Die aktuelle darf nicht entfernt werden, da sonst
* listNextMess nicht funktioniert
*)
INCL (list^[idx].flags, Selected);
(* Und jetzt Liste verkleinern *)
IF ~shrinkList (ptr, FALSE, TRUE)
THEN
WdwManager.FullRedrawWdw (wdw);
END;
END;
END;
END;
END listRemoveTree;
PROCEDURE listChangeFlags (hdl: LONGCARD; grinWdw: INTEGER;
msgNum: CARDINAL; newBits: BITSET);
(* grin teilt der Stichwortliste mit, da sich bei einer Nachricht
* die Flags gendert haben
*)
VAR ptr: listWdwPtr;
idx: CARDINAL;
BEGIN
IF handlePool.FindEntry(ADR(hdl), FindHandleCond, windows, ptr)
THEN
IF grinWdw # ptr^.grinWindow
THEN
RETURN
END;
WITH ptr^ DO
findMsgIdx (ptr, msgNum, idx);
IF idx < dataSys.notSaved
THEN
IF dataSys.bGelesen IN newBits
THEN
EXCL (list^[idx].flags, notRead);
ELSE
INCL (list^[idx].flags, notRead);
END;
(* Eintrag mu komplett neu gezeichnet werden *)
INCL (list^[idx].flags, doRedraw);
END;
END;
END;
END listChangeFlags;
(*$H+*)
PROCEDURE listOpenWithProc (gruppe : CARDINAL; whichNr : getNumberProc; grinWdw : INTEGER; mode: grin.openMode);
(* Ein Stichwortlistenfenster wird geffnet *)
VAR ptr : listWdwPtr;
handlePtr : handlePool.oneHandlePtr;
varName : ARRAY[0..39] OF CHAR;
work : GrafBase.Rectangle;
comps : BITSET;
i : CARDINAL;
which : CARDINAL;
openNew : BOOLEAN;
num : INTEGER;
saveVar : SearchHelp.SearchRecordType;
doRedraw : BOOLEAN;
BEGIN
IF handlePool.FindEntry (ADR (gruppe), FindGroupCond, windows, ptr)
THEN
IF ptr^.wdw >= 0
THEN
(* Gruppe schon als Stichwortfenster offen *)
WdwManager.TopWindow (ptr^.wdw);
openNew := FALSE;
ELSE
openNew := TRUE;
END;
ELSE
ptr := NIL;
openNew := FALSE;
END;
IF (ptr = NIL) OR openNew
THEN
(* Gruppe ffnen und Stichwortliste anzeigen *)
IF ((ptr = NIL) & handlePool.BlankToList(ptr, TSIZE(listWindow), windows)) OR openNew THEN
IF openNew OR (~openNew & handlePool.GetOneDatahandle(gruppe, handlePtr)) THEN
IF openNew
THEN
handlePtr := ptr^.grHandle;
END;
ptr^.wdw := -1;
which := whichNr (handlePtr^.Zugriff);
ptr^.grHandle := handlePtr;
ptr^.grinWindow := grinWdw;
(* Fensternummer dieses Moduls herausfinden *)
ptr^.number := FindNum ();
Strings.Concat (cListWdw, StrConv.IntToStr (ptr^.number, 0), varName,
v.bool);
IF ~ConfVars.GetConfigRect (varName, ptr^.listWork)
THEN
IF (ptr^.number > 0)
THEN
num := ptr^.number - 1;
Strings.Concat (cListWdw, StrConv.IntToStr (num, 0), varName,
v.bool);
END;
ConfVars.GetConfDefRect (varName, ptr^.listWork, EditTypes.deskSize);
IF ~ RectFuncs.RectEqual (ptr^.listWork, EditTypes.deskSize)
THEN
INC (ptr^.listWork.x, 2*mtAppl.CharWidth);
INC (ptr^.listWork.y, mtAppl.CharHeight);
END;
Strings.Concat (cListWdw, StrConv.IntToStr (ptr^.number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigRect (varName, ptr^.listWork);
END;
ConfVars.GetConfDefInt (cListLeftOffset, pixOffset, pixOffset);
pixOffset := BinOps.HigherInt (0, pixOffset);
ConfVars.GetConfDefInt (cListLineDist, lineDist, lineDist);
lineDist := BinOps.HigherInt (0, lineDist);
(* Fensterkomponenten setzen *)
comps := {MagicAES.NAME..MagicAES.HSLIDE};
(* Infozeile brauchen wir nicht *)
EXCL (comps, MagicAES.INFO);
IF ~openNew
THEN
MakeTitle (gruppe, ptr^.grName);
ptr^.maxPos := data.LastMsgOfGroup (gruppe);
IF ptr^.maxPos = dataSys.empty
THEN
handlePool.FreeOneDataHandle(handlePtr);
handlePool.FreeOnePtr (ptr, windows);
ClearNum (ptr^.number);
RETURN
END;
IF which > ptr^.maxPos THEN which := ptr^.maxPos END;
ptr^.usedByGrin := 0;
(* Jetzt "Liste" aufbauen *)
ALLOCATE (ptr^.wholeList, LONG(ptr^.maxPos + 1) * LONG(TSIZE (listEntry)));
ptr^.list := ptr^.wholeList;
END;
IF ptr^.wholeList # NIL THEN
IF ~openNew
THEN
(* Liste fllen *)
FOR i := 0 TO ptr^.maxPos DO
ptr^.wholeList^[i] := listEntry(lEntry{i, {}, NIL});
END;
END;
ptr^.charHeight := 1;
ptr^.charWidth := 8;
ptr^.font := -1;
ptr^.fontSize := 10;
IF gruppe = dataSys.private
THEN
ptr^.partArray := privateParts;
ELSE
ptr^.partArray := globalParts;
END;
(* Fenster ffnen *)
IF WdwManager.OpenWindow (clickInListWindow, handleListKey, handleListTimer,
EditTypes.deskSize, ptr^.listWork, comps, TRUE,
'', ptr^.grName, snapListWdw, closeListWindow,
drawListWdw, topListWdw, untopListWdw, updateListWdw,
setListWork, getListScroll, hideListWdw,
pixOffset, ptr, FALSE, TRUE, TRUE, TRUE,
ptr^.wdw, ptr^.vdi)
THEN
WITH ptr^ DO
(* Als DDServer installieren *)
WdwManager.WdwInstallDDServer (wdw, listGetHeader, listReadData);
isHidden := FALSE;
(* grin Bescheid sagen *)
v.bool := grin.grinSetListWdw (grinWindow, grin.grinNextMess, LONGCARD(ptr));
(* Kein Cursor am Anfang *)
cursPos := -1;
(* Font aus Configvariablen lesen und setzen *)
Strings.Concat (cListFont, StrConv.IntToStr (number, 0), varName, v.bool);
IF ~ConfVars.GetConfigInt (varName, font)
THEN
num := BinOps.HigherInt (number-1, 0);
Strings.Concat (cListFont, StrConv.IntToStr (num, 0), varName, v.bool);
ConfVars.GetConfDefInt (varName, font, 1);
Strings.Concat (cListSize, StrConv.IntToStr (num, 0), varName,
v.bool);
ConfVars.GetConfDefInt (varName, fontSize, 10);
Strings.Concat (cListFont, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, font);
Strings.Concat (cListSize, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, fontSize);
ELSE
Strings.Concat (cListSize, StrConv.IntToStr (number, 0), varName, v.bool);
ConfVars.GetConfDefInt (varName, fontSize, 10);
END;
findMsgIdx (ptr, which, startPos);
leftOffset := 0;
maxWidth := 0;
(* Modus merken *)
unreadOrNew := (mode=grin.mFirstNew) OR (mode=grin.mUnread);
openMode := mode;
isLocked := FALSE;
doRedraw := FALSE;
(* Jetzt eventuell Liste verkleinern *)
ConfVars.GetConfDefBool (cListShrink, v.bool, FALSE);
IF unreadOrNew & v.bool
THEN
(* Liste verkleinern *)
shrinkToEnd (ptr, FALSE);
(* doRedraw := TRUE; *)
END;
(* Jetzt eventuell gefilterte rausnehmen *)
ConfVars.GetConfDefBool (cListFilter, v.bool, FALSE);
IF unreadOrNew & v.bool
THEN
(* Gefilterte selektieren und dann Liste verkleinern *)
listSelectFiltered (ptr^.wdw, TRUE, FALSE);
v.bool := shrinkList (ptr, TRUE, FALSE);
(* doRedraw := TRUE; *)
END;
(* Jetzt mal nachsehen, ob wir auch sortieren mssen *)
ConfVars.GetConfDefInt (cListSort, v.int, 3);
IF unreadOrNew & (sortType(v.int) # sNum)
THEN
isLocked := TRUE;
doSort (ptr, sortType(v.int), FALSE);
doRedraw := TRUE;
isLocked := FALSE;
END;
IF unreadOrNew
THEN
saveVar := SearchHelp.suchVar;
FOR i := 1 TO 10 DO
MagicStrings.Assign (cListSearch, varName);
MagicStrings.Append (StrConv.CardToStr (i, 0), varName);
ConfVars.GetConfDefBool (varName, v.bool, FALSE);
IF v.bool
THEN
isLocked := TRUE;
(* Ok, steht auf TRUE, also selektieren *)
IF SearchHelp.getKonf (i-1, SearchHelp.suchVar)
& SearchHelp.ValidateKonf (SearchHelp.suchVar)
THEN
doMark (ptr, FALSE);
doRedraw := TRUE;
END;
isLocked := FALSE;
END;
END;
SearchHelp.suchVar := saveVar;
END;
(* Noch ein bichen was fr die Window-Library *)
WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, FALSE);
(* Fonts laden *)
FontSelect.LoadFonts (vdi, v.int);
(* Font setzen *)
iListSetFont (wdw, font, fontSize, FALSE);
(* Jetzt noch ein paar andere VDI-Variablen setzen *)
v.int := MagicVDI.SetFillstyle (vdi, MagicVDI.Full);
v.int := MagicVDI.SetFillinterior (vdi, MagicVDI.Full);
v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.listBackCol);
(* Schreibmodus setzen *)
v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE);
IF doRedraw
THEN
WdwManager.FullRedrawWdw (ptr^.wdw);
END;
END;
ELSE
handlePool.FreeOneDataHandle(handlePtr);
handlePool.FreeOnePtr (ptr, windows);
ClearNum (ptr^.number);
MTE.info ("CAT:|Es ist kein Fenster oder|keine VDI-Workstation fr|die Stichwortliste mehr frei.][[Abbruch]"); END;
ELSE
handlePool.FreeOneDataHandle(handlePtr);
handlePool.FreeOnePtr (ptr, windows);
ClearNum (ptr^.number);
MTE.noMemAlert();
END;
ELSE
handlePool.FreeOnePtr (ptr, windows);
MTE.noMemAlert();
END;
ELSE
MTE.noMemAlert();
END;
END;
END listOpenWithProc;
PROCEDURE listOpen (gruppe, which : CARDINAL; grinWindow : INTEGER; mode: grin.openMode);
(* Ein Stichwortlistenfenster wird geffnet,
* die Nummer wird ber eine Prozedur ermittelt
*)
PROCEDURE Standard(ptr : data.OneGroupHandle):CARDINAL;
BEGIN
RETURN which
END Standard;
BEGIN
listOpenWithProc(gruppe, Standard, grinWindow, mode);
END listOpen;
(*$H=*)
PROCEDURE listClose (wdw : INTEGER);
(* Ein Stichwortlistenfenster wird geschlossen *)
VAR p : listWdwPtr;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
v.bool := WdwManager.CloseWindow (wdw, TRUE);
END;
END listClose;
PROCEDURE listSelectAll(wdw : INTEGER; withRedraw: BOOLEAN);
(* Alle Nachrichten in dem Fenster werden selektiert *)
VAR p : listWdwPtr;
i : CARDINAL;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
WITH p^ DO
CatGlobal.busyMouse();
FOR i := 0 TO maxPos DO
INCL (list^[i].flags, Selected);
IF (i MOD 75 = 0) THEN
CatGlobal.busyMouse();
END;
END;
mtAppl.MouseArrow();
END;
(* Und jetzt vorsichtshalber Redraw auslsen *)
IF withRedraw
THEN
WdwManager.FullRedrawWdw (wdw);
END;
END;
END listSelectAll;
PROCEDURE listSelectNew(wdw : INTEGER);
(* Alle Nachrichten in dem Fenster werden selektiert *)
VAR p : listWdwPtr;
start,
i : CARDINAL;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
WITH p^ DO
CatGlobal.busyMouse();
start := data.FirstNewMsg(grHandle^.group);
(* Jetzt die erste Message finden, deren Nummer > start ist *)
FOR i := 0 TO maxPos DO
IF (list^[i].msgNum >= start)
THEN
INCL (list^[i].flags, Selected);
IF (i MOD 75 = 0) THEN
CatGlobal.busyMouse();
END;
END;
END;
mtAppl.MouseArrow();
END;
(* Und jetzt vorsichtshalber Redraw auslsen *)
WdwManager.FullRedrawWdw (wdw);
END;
END listSelectNew;
(*-- Ausgabefunktionen -------------------------------------------------*)
CONST smListe = 1;
smOutfile = 2;
smText = 3;
smData = 4;
smDecode = 5;
smStatus = 6;
PROCEDURE listSaveStatus (ptr: listWdwPtr; f: mtTextfiles.TEXTFILE);
VAR firstSel,
msgNum : CARDINAL;
idx : CARDINAL;
mess : data.MessageType;
line : CatTypes.String255;
status : CatTypes.String255;
j : INTEGER;
BEGIN
WITH ptr^ DO
IF hasSelectedEntries (ptr, firstSel)
THEN
msgNum := list^[firstSel].msgNum;
idx := firstSel;
WHILE msgNum < dataSys.notSaved DO
(* Header der Message lesen *)
data.ReadHeader (grHandle^.Zugriff, msgNum, mess);
IF data.error = data.noError
THEN
(* MsgId ausgeben *)
mtTextfiles.WriteLine (f, "#");
mtTextfiles.WriteLine (f, mess.MailID^);
mtTextfiles.WriteLn (f);
(* Status ausgeben *)
mtTextfiles.WriteLine (f, "BG");
mtTextfiles.WriteLn (f);
IF mess.InfoStrings # NIL THEN
DEALLOCATE (mess.InfoStrings, 0);
END;
END;
(* Nchste selektierte finden *)
INC (idx);
WHILE (idx <= maxPos) & ~(Selected IN list^[idx].flags) DO INC (idx) END;
IF idx <= maxPos
THEN
msgNum := list^[idx].msgNum;
ELSE
msgNum := dataSys.empty;
END;
END;
END;
END;
END listSaveStatus;
PROCEDURE listSaveList (ptr: listWdwPtr; f: mtTextfiles.TEXTFILE);
VAR firstSel,
msgNum : CARDINAL;
idx : CARDINAL;
mess : data.MessageType;
line : CatTypes.String255;
width : INTEGER;
j : INTEGER;
BEGIN
WITH ptr^ DO
IF hasSelectedEntries (ptr, firstSel)
THEN
msgNum := list^[firstSel].msgNum;
idx := firstSel;
WHILE msgNum < dataSys.notSaved DO
(* Header der Message lesen *)
data.ReadHeader (grHandle^.Zugriff, msgNum, mess);
IF data.error # data.noError
THEN
WITH mess DO
MailID := NIL;
Betreff := NIL;
Absender := NIL;
Empfaenger := NIL;
mid := NIL;
rid := NIL;
box := NIL;
name := NIL;
mime := NIL;
gate := NIL;
followupTo := NIL;
replyTo := NIL;
gate := NIL;
InfoStrings := NIL;
END;
END;
(* Zeile ausgeben *)
FOR j := 0 TO partArray.lines-1 DO
GetLinePart (ptr, msgNum, mess, line, partArray.parts[j]);
width := partArray.parts[j].w;
mtTextfiles.WriteLine (f, line);
mtTextfiles.WriteLine (f, Strings.Space (width - INTEGER(LENGTH (line))));
mtTextfiles.WriteChar (f, ' ');
END;
mtTextfiles.WriteLn (f);
IF mess.InfoStrings # NIL THEN
DEALLOCATE (mess.InfoStrings, 0);
END;
(* Nchste selektierte finden *)
INC (idx);
WHILE (idx <= maxPos) & ~(Selected IN list^[idx].flags) DO INC (idx) END;
IF idx <= maxPos
THEN
msgNum := list^[idx].msgNum;
ELSE
msgNum := dataSys.empty;
END;
END;
END;
END;
END listSaveList;
PROCEDURE LineOut (file : mtTextfiles.TEXTFILE; ch : ARRAY OF CHAR; str : CatTypes.Str255Ptr);
BEGIN
IF str = NIL THEN RETURN END;
IF str^[0] = 0C THEN RETURN END;
IF ch[0] # 0C THEN mtTextfiles.WriteLine (file, ch); END;
mtTextfiles.WriteLine (file, str^);
mtTextfiles.WriteLn (file);
END LineOut;
PROCEDURE buildDate (date: LONGCARD; VAR str : ARRAY OF CHAR);
BEGIN
MagicStrings.Assign (StrConv.LNumToStr (date, 10, 9, '0'), str);
Strings.Insert ('199', 0, str, v.bool);
END buildDate;
PROCEDURE buildFlagLine (flags: BITSET; VAR str : ARRAY OF CHAR);
VAR i : INTEGER;
(* zur Definition der eigenen Flagzeile verweise ich auf
* parser.CheckFlagLine
*)
BEGIN
i := 0;
IF dataSys.bGelesen IN flags THEN str[i] := 'G'; INC (i); END;
IF dataSys.bTotalloeschung IN flags THEN str[i] := 'X'; INC (i); END;
IF dataSys.bInteressant IN flags THEN str[i] := 'F'; INC (i); END;
IF dataSys.bFiltered IN flags THEN str[i] := 'L'; INC (i); END;
IF dataSys.bTeilloeschung IN flags THEN str[i] := 'D'; INC (i); END;
IF dataSys.bKommentieren IN flags THEN str[i] := 'K'; INC (i); END;
IF dataSys.bAntworten IN flags THEN str[i] := 'B'; INC (i); END;
IF dataSys.bVererben IN flags THEN str[i] := 'V'; INC (i); END;
IF dataSys.bUser1 IN flags THEN str[i] := 'C'; INC (i); END;
IF dataSys.bUser2 IN flags THEN str[i] := 'M'; INC (i); END;
str[i] := 0C;
END buildFlagLine;
PROCEDURE messageOut (f: mtTextfiles.TEXTFILE; mess: data.MessageType; REF pre: ARRAY OF CHAR);
VAR idx : CARDINAL;
lfDone : BOOLEAN;
ch : CHAR;
BEGIN
WITH mess DO
IF Text = NIL THEN RETURN END;
(* Und jetzt knnen wir den Text ausgeben *)
idx := 0;
lfDone := TRUE;
WHILE idx < textLen DO
ch := Text^[idx];
IF ch # LF
THEN
IF lfDone THEN mtTextfiles.WriteLine (f, pre); lfDone := FALSE; END;
mtTextfiles.WriteChar (f, ch);
ELSE
IF lfDone THEN mtTextfiles.WriteLine (f, pre); END;
mtTextfiles.WriteLn (f);
lfDone := TRUE;
END;
INC (idx);
END;
IF ~lfDone THEN mtTextfiles.WriteLn (f); END;
END;
END messageOut;
PROCEDURE listSaveOutfile (ptr: listWdwPtr; f: mtTextfiles.TEXTFILE; append: BOOLEAN);
VAR firstSel : CARDINAL;
msgNum : CARDINAL;
idx : CARDINAL;
groupName : CatTypes.String255;
dateLine : CatTypes.String127;
mess : data.MessageType;
fPos : LONGCARD;
BEGIN
WITH ptr^ DO
IF hasSelectedEntries (ptr, firstSel)
THEN
IF append
THEN
(* #CRLF am Dateiende entfernen *)
fPos := mtTextfiles.Textpos (f);
(* Ein Test ist hier nicht ntig, append wird nur
* gesetzt, wenn es mglich ist
*)
mtTextfiles.SetTextpos (f, fPos-3);
END;
(* Gruppennamen rausfinden *)
IF grHandle^.group = dataSys.private
THEN
MagicStrings.Assign ('', groupName);
ELSE
GroupSelect.GroupName (grHandle^.group, groupName);
END;
msgNum := list^[firstSel].msgNum;
idx := firstSel;
WHILE msgNum < dataSys.notSaved DO
(* Message lesen *)
data.ReadMessage (grHandle^.Zugriff, msgNum, mess);
IF data.error = data.noError
THEN
WITH mess DO
(* Header ausgeben *)
LineOut (f, '#', MailID);
IF (grHandle^.group = dataSys.private) & (mess.EigeneNachricht)
& ((Absender = NIL) OR (Absender^[0] = 0C))
THEN
LineOut (f, 'V', ADR(CatGlobal.userName));
ELSE
LineOut (f, 'V', Absender);
END;
LineOut (f, 'W', Betreff);
LineOut (f, 'A', Empfaenger);
LineOut (f, 'G', ADR(groupName));
(* Datum noch holen *)
buildDate (tauschDate, dateLine);
LineOut (f, 'E', ADR (dateLine));
LineOut (f, '-', ADR (KommentierteID));
(* Jetzt noch den Usenet-Krempel *)
LineOut (f, 'N', name);
LineOut (f, 'I', mid);
LineOut (f, 'R', rid);
LineOut (f, 'O', box);
LineOut (f, 'M', mime);
LineOut (f, 'F', followupTo);
LineOut (f, 'T', replyTo);
LineOut (f, 'Y', gate);
(* Distribution rauspusten *)
IF distribution # data.dNone
THEN
dateLine [0] := CHR(ORD(distribution) + ORD('K'));
dateLine [1] := 0C;
LineOut (f, 'D', ADR(dateLine));
END;
(* Bei der persnlichen Gruppe mu eine Statuszeile ausgegeben werden
*)
IF grHandle^.group = dataSys.private
THEN
buildDate (statusDate, dateLine);
MagicStrings.Insert (Status, dateLine, 0);
LineOut (f, 'B', ADR(dateLine));
END;
(* Jetzt noch die Statuszeile *)
buildFlagLine (StatusBits, dateLine);
LineOut (f, 's', ADR(dateLine));
(* Und jetzt knnen wir den Text ausgeben *)
messageOut (f, mess, ':');
(* Speicher freigeben *)
DEALLOCATE (Text, 0);
DEALLOCATE (InfoStrings, 0);
END; (* WITH mess DO *)
END; (* IF data.error *)
(* Nchste selektierte finden *)
INC (idx);
WHILE (idx <= maxPos) & ~(Selected IN list^[idx].flags) DO INC (idx) END;
IF idx <= maxPos
THEN
msgNum := list^[idx].msgNum;
ELSE
msgNum := dataSys.empty;
END;
END; (* WHILE *)
(* Jetzt noch das Logfile schreiben *)
mtTextfiles.WriteLine (f, '#LOG');
mtTextfiles.WriteLn (f);
LineOut (f, ':!V', CADR(CatTypes.CatDate));
MagicStrings.Assign ('CAT ', dateLine);
MagicStrings.Append (CatTypes.CatVersion, dateLine);
LineOut (f, ':!', ADR(dateLine));
MagicStrings.Assign ('Database von ', dateLine);
MagicStrings.Append (CatGlobal.userName, dateLine);
LineOut (f, ':!', ADR(dateLine));
mtTextfiles.WriteLine (f, '#');
mtTextfiles.WriteLn (f);
END; (* IF hasSelectedEntries *)
END; (* WITH ptr^ DO *)
END listSaveOutfile;
PROCEDURE listSaveText (ptr: listWdwPtr; f: mtTextfiles.TEXTFILE; dataMode: BOOLEAN);
VAR firstSel : CARDINAL;
msgNum : CARDINAL;
idx : CARDINAL;
groupName : CatTypes.String255;
tmpLine : CatTypes.String255;
mess : data.MessageType;
i : INTEGER;
emptyLines: INTEGER;
BEGIN
WITH ptr^ DO
IF hasSelectedEntries (ptr, firstSel)
THEN
ConfVars.GetConfDefInt (cPrtLines, emptyLines, 1);
(* Gruppennamen rausfinden *)
GroupSelect.GroupName (grHandle^.group, groupName);
msgNum := list^[firstSel].msgNum;
idx := firstSel;
WHILE msgNum < dataSys.notSaved DO
(* Message lesen *)
data.ReadMessage (grHandle^.Zugriff, msgNum, mess);
IF data.error = data.noError
THEN
WITH mess DO
IF ~dataMode
THEN
(* Header ausgeben *)
LineOut (f, 'ID : ', MailID);
LineOut (f, 'Gruppe: ', ADR(groupName));
LineOut (f, 'Followup-To: ', followupTo);
LineOut (f, 'Kommentar zu ', ADR (KommentierteID));
IF Absender # NIL
THEN
MagicStrings.Assign (Absender^, tmpLine);
MagicStrings.Append(' (', tmpLine);
MagicStrings.Append(Datum, tmpLine);
MagicStrings.Append(')', tmpLine);
LineOut (f, 'Von : ', ADR(tmpLine));
END;
LineOut (f, 'Name: ', name);
LineOut (f, 'Reply-To: ', replyTo);
LineOut (f, 'Wg. : ', Betreff);
IF Empfaenger # NIL
THEN
MagicStrings.Assign (Empfaenger^, tmpLine);
IF (Gruppe = dataSys.private) &
EigeneNachricht
THEN
MagicStrings.Append(' (', tmpLine);
MagicStrings.Append(Datum, tmpLine);
MagicStrings.Append(')', tmpLine);
END;
LineOut (f, 'An : ', ADR(tmpLine));
END;
(* Jetzt noch den Usenet-Krempel *)
LineOut (f, 'Box : ', box);
LineOut (f, 'MId : ', mid);
LineOut (f, 'RId : ', rid);
LineOut (f, 'Gate: ', gate);
LineOut (f, 'MIME: ', mime);
mtTextfiles.WriteLn (f);
END;
(* Und jetzt knnen wir den Text ausgeben *)
messageOut (f, mess, '');
IF ~dataMode
THEN
(* Jetzt noch ein paar Trennzeilen *)
FOR i := 0 TO emptyLines-1 DO
mtTextfiles.WriteLn (f);
END;
END;
(* Speicher freigeben *)
DEALLOCATE (Text, 0);
DEALLOCATE (InfoStrings, 0);
END; (* WITH mess DO *)
END; (* IF data.error *)
(* Nchste selektierte finden *)
INC (idx);
WHILE (idx <= maxPos) & ~(Selected IN list^[idx].flags) DO INC (idx) END;
IF idx <= maxPos
THEN
msgNum := list^[idx].msgNum;
ELSE
msgNum := dataSys.empty;
END;
END; (* WHILE *)
END; (* IF hasSelectedEntries *)
END; (* WITH ptr^ DO *)
END listSaveText;
PROCEDURE listDecode (ptr: listWdwPtr);
VAR firstSel : CARDINAL;
msgNum : CARDINAL;
idx : CARDINAL;
mess : data.MessageType;
i : INTEGER;
textIdx : CARDINAL;
line,
text : POINTER TO ARRAY [0..32767] OF CHAR;
chPtr : POINTER TO CHAR;
saveCh : CHAR;
BEGIN
WITH ptr^ DO
IF hasSelectedEntries (ptr, firstSel)
THEN
msgNum := list^[firstSel].msgNum;
idx := firstSel;
CatGlobal.busyMouse();
UUDecode.BeginDecode ();
WHILE msgNum < dataSys.notSaved DO
(* Message lesen *)
CatGlobal.busyMouse();
data.ReadMessage (grHandle^.Zugriff, msgNum, mess);
IF data.error = data.noError
THEN
WITH mess DO
textIdx := 0;
chPtr := ADDRESS(Text);
REPEAT
(* Startadresse festlegen *)
text := ADDRESS(chPtr);
(* Zeilenende suchen *)
WHILE (chPtr^ # CR) & (chPtr^ # LF) & (textIdx < textLen) DO
INC (textIdx);
INC (chPtr);
END;
saveCh := chPtr^;
chPtr^ := 0C;
IF ~UUDecode.DecodeLine (text^)
THEN
MTE.info ("[3][CAT:|Beim Decodieren des Textes ist|ein Fehler aufgetreten!][:[Abbruch]");
DEALLOCATE (Text, 0);
DEALLOCATE (InfoStrings, 0);
UUDecode.EndDecode ();
mtAppl.MouseArrow();
RETURN
END;
chPtr^ := saveCh;
INC (textIdx);
INC (chPtr);
(* Nchsten Zeilenanfang finden *)
WHILE (chPtr^ = CR) & (chPtr^ = LF) & (textIdx < textLen) & (chPtr^ # saveCh) DO
INC (textIdx);
END;
UNTIL (textIdx >= textLen);
(* Speicher freigeben *)
DEALLOCATE (Text, 0);
DEALLOCATE (InfoStrings, 0);
END; (* WITH mess DO *)
END; (* IF data.error *)
(* Nchste selektierte finden *)
INC (idx);
WHILE (idx <= maxPos) & ~(Selected IN list^[idx].flags) DO INC (idx) END;
IF idx <= maxPos
THEN
msgNum := list^[idx].msgNum;
ELSE
msgNum := dataSys.empty;
END;
END; (* WHILE *)
UUDecode.EndDecode ();
mtAppl.MouseArrow();
END; (* IF hasSelectedEntries *)
END; (* WITH ptr^ DO *)
END listDecode;
PROCEDURE listSave (ptr : listWdwPtr; REF path, name : ARRAY OF CHAR;
saveMode : INTEGER; askOverwrite: BOOLEAN; append: BOOLEAN);
VAR fname : CatTypes.String255;
fileOpenMode: mtTextfiles.Textmode;
exists : BOOLEAN;
out : mtTextfiles.TEXTFILE;
isOutfile : BOOLEAN;
tmp : ARRAY [0..3] OF CHAR;
fPos : LONGCARD;
i : INTEGER;
BEGIN
WITH ptr^ DO
(* Dateinamen basteln *)
MagicStrings.Assign (path, fname);
MagicStrings.Append (name, fname);
(* Erstmal feststellen, ob die Datei existiert *)
fPos := CatFiles.FileSize (fname, exists);
fileOpenMode := mtTextfiles.WRITE;
IF exists
THEN
IF askOverwrite
THEN
v.int := mtAlerts.Alert (2,MTE.Overwrite);
IF v.int = 3 THEN
RETURN
ELSIF v.int = 2
THEN
fileOpenMode := mtTextfiles.APPEND;
ELSE
fileOpenMode := mtTextfiles.WRITE;
END;
ELSE
IF append
THEN
fileOpenMode := mtTextfiles.APPEND;
ELSE
fileOpenMode := mtTextfiles.WRITE;
END;
END;
END;
isOutfile := FALSE;
IF fileOpenMode = mtTextfiles.APPEND
THEN
(* Erstmal kurz die letzten drei Byte lesen *)
IF mtTextfiles.OpenTextfile (fname, mtTextfiles.READ, 32768, out)
THEN
(* In fPos steht schon die Gre *)
IF (fPos >= 3)
THEN
mtTextfiles.SetTextpos (out, fPos-3);
FOR i := 0 TO 2 DO
mtTextfiles.ReadChar (out, tmp[i]);
END;
tmp[3] := 0C;
(* Jetzt Test auf #CRLF *)
IF MagicStrings.Equal (tmp, "#"+CR+LF)
THEN
isOutfile := TRUE;
END;
END;
mtTextfiles.CloseTextfile (out);
END;
END;
(* So, jetzt die Datei ffnen *)
IF mtTextfiles.OpenTextfile (fname, fileOpenMode, 32768, out)
THEN
mtAppl.MouseBusy();
CASE saveMode OF
smListe : listSaveList (ptr, out); |
smOutfile: listSaveOutfile (ptr, out, isOutfile); |
smText : listSaveText (ptr, out, FALSE); |
(*
smData : listSaveText (ptr, out, TRUE); |
*)
smStatus: listSaveStatus (ptr, out); |
ELSE
END;
mtTextfiles.CloseTextfile(out);
mtAppl.MouseArrow();
ELSE
MTE.info (MTE.NoWrite);
END;
END;
END listSave;
PROCEDURE listSaveAs (wdw: INTEGER);
(* Speichert die selektierten Nachrichten in einer Datei *)
VAR p : listWdwPtr;
saveMode : INTEGER;
kstate : BITSET;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
IF hasSelectedEntries (p, v.card)
THEN
saveMode := mtAlerts.Alert (lastSaveMode, MTE.listMode);
MagicAES.GrafMkstate (v.int, v.int, v.bset, kstate);
IF saveMode = 5 THEN RETURN END;
lastSaveMode := saveMode;
IF (saveMode = 1) & (CatGlobal.WithCtrl (kstate))
THEN
v.int := mtAlerts.Alert (2, "[2][CAT:|Liste als Statusmeldungen sichern?][[Abbruch|[OK]");
IF v.int = 2
THEN
saveMode := 6;
END;
END;
IF saveMode = 4
THEN
listDecode (p);
ELSE
(* Jetzt Datei auswhlen *)
IF CatGlobal.FselGet (CatGlobal.SavePath, CatGlobal.SaveName, '*.txt', 'Nachrichten speichern als...', FALSE)
THEN
(* Ok, Name ist ausgewhlt *)
listSave (p, CatGlobal.SavePath, CatGlobal.SaveName, saveMode, TRUE, FALSE);
Protokoll.SendPathUpdate (CatGlobal.SavePath);
END;
END;
END;
END;
END listSaveAs;
CONST
ScrapName = 'SCRAP.TXT';
PROCEDURE listCopy(wdw : INTEGER);
(* Alle selektierten Nachrichten werden exportiert*)
VAR p : listWdwPtr;
append : BOOLEAN;
state : BITSET;
path : CatTypes.String255;
saveMode : INTEGER;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
IF hasSelectedEntries (p, v.card)
THEN
MagicAES.GrafMkstate(v.int, v.int, v.bset, state);
append := CatGlobal.WithShift (state);
IF Clip.GetScrap (path)
THEN
saveMode := mtAlerts.Alert (lastSaveMode, MTE.listMode);
IF saveMode = 5 THEN RETURN END;
(*
IF (saveMode = smOutfile) & (p^.grHandle^.group = dataSys.private)
THEN
v.int := mtAlerts.Alert (2, MTE.expPrivate);
IF v.int = 1 THEN RETURN END;
END;
*)
lastSaveMode := saveMode;
IF append
THEN
Clip.ScrapClear ("", ScrapName);
ELSE
Clip.ScrapClear ("", "");
END;
IF saveMode = 4
THEN
listDecode (p);
ELSE
listSave (p, path, ScrapName, saveMode, FALSE, append);
END;
END;
END;
END;
END listCopy;
PROCEDURE listSomethingSelected (wdw: INTEGER): BOOLEAN;
(* Gibt zurck, ob in der Stichwortliste Nachrichten markiert
* sind
*)
VAR p : listWdwPtr;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
RETURN hasSelectedEntries (p, v.card);
END;
RETURN FALSE;
END listSomethingSelected;
PROCEDURE listSetFlags(wdw : INTEGER; setBits, clearBits : BITSET);
(* Fr alle selektierten Nachrichten
* ein paar Flags setzen oder lschen
*)
VAR p : listWdwPtr;
bits,
newBits : BITSET;
(*$Reg*) counter : CARDINAL;
(*$Reg*) i : CARDINAL;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
WITH p^ DO
CatGlobal.busyMouse();
counter := 0;
FOR i := 0 TO maxPos DO
IF Selected IN list^[i].flags THEN
data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
IF data.error = data.noError
THEN
(* Neue Flags berechnen *)
newBits := (bits-clearBits)+setBits;
(* Flags setzen *)
data.SetBits(grHandle^.Zugriff, list^[i].msgNum, newBits);
INC (counter);
IF counter MOD 50 = 0 THEN CatGlobal.busyMouse(); END;
END;
END;
END;
mtAppl.MouseArrow();
END;
(* Und jetzt vorsichtshalber Redraw auslsen *)
WdwManager.FullRedrawWdw (wdw);
END;
END listSetFlags;
PROCEDURE listSavePos();
VAR lauf : listWdwPtr;
varName : ARRAY [0..255] OF CHAR;
full : GrafBase.Rectangle;
BEGIN
Lists.ResetList(windows);
lauf := Lists.NextEntry(windows);
WHILE lauf # NIL DO
WITH lauf^ DO
IF wdw > 0
THEN
Strings.Concat (cListGroup, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigLongInt (varName, VAL(LONGINT, grHandle^.group));
Strings.Concat (cListStart, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigLongInt (varName, VAL(LONGINT, startPos));
Strings.Concat (cListWdw, StrConv.IntToStr (number, 0), varName, v.bool);
WdwManager.GetWdwSize (wdw, full); (* Gre des Fensters abfragen *)
v.bool := ConfVars.SetConfigRect (varName, full);
Strings.Concat (cListFont, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, font);
Strings.Concat (cListSize, StrConv.IntToStr (number, 0), varName, v.bool);
v.bool := ConfVars.SetConfigInt (varName, fontSize);
END;
END;
lauf := Lists.NextEntry(windows);
END;
END listSavePos;
PROCEDURE listRestorePos();
VAR varName : ARRAY [0..255] OF CHAR;
number : INTEGER;
gruppe,
mailNr : CARDINAL;
BEGIN
FOR number := 0 TO 255 DO
Strings.Concat (cListGroup, StrConv.IntToStr (number, 0), varName, v.bool);
IF ConfVars.GetConfigLongInt (varName, v.lint)
THEN
gruppe := VAL (CARDINAL, v.lint);
Strings.Concat (cListStart, StrConv.IntToStr (number, 0), varName, v.bool);
IF ConfVars.GetConfigLongInt (varName, v.lint)
THEN
mailNr := VAL (CARDINAL, v.lint);
globalNumber := number;
listOpen (gruppe, mailNr, -1, grin.mOther);
END;
END;
END;
globalNumber := -1;
END listRestorePos;
PROCEDURE listCloseAll ();
(* Alle Sichwortlistenfenster werden geschlossen *)
VAR lauf : listWdwPtr;
BEGIN
Lists.ResetList(windows);
lauf := Lists.NextEntry(windows);
WHILE lauf # NIL DO
listClose(lauf^.wdw);
lauf := Lists.NextEntry(windows);
END;
END listCloseAll;
PROCEDURE listFreeAll();
(* Schliet alle Stichwortlistenfenster und gibt auch alle Handles wieder
* frei
*)
VAR lauf : listWdwPtr;
BEGIN
listCloseAll();
Lists.ResetList (windows);
lauf := Lists.NextEntry (windows);
WHILE lauf # NIL DO
IF lauf^.usedByGrin > 0
THEN
freeList (lauf);
handlePool.FreeOneDataHandle(lauf^.grHandle);
handlePool.FreeOnePtr(lauf, windows);
Lists.ResetList (windows);
END;
lauf := Lists.NextEntry (windows);
END;
END listFreeAll;
PROCEDURE listWindowTop (wdw : INTEGER) : BOOLEAN;
(* Ist ein Stichwortlistenfenster oben? *)
BEGIN
RETURN handlePool.FindEntry(ADR(wdw), FindWinCond, windows, v.a);
END listWindowTop;
PROCEDURE listSetFont (wdw: INTEGER; font, fontSize : INTEGER);
BEGIN
iListSetFont (wdw, font, fontSize, TRUE);
END listSetFont;
PROCEDURE listCloseByHandle (hdl : LONGCARD);
(* Ein Stichwortlistenfenster wird ber das assoziierte Handle
* geschlossen, wird von grin aufgerufen, wenn ein Fenster mit
* geschlossen wird, an das eine Stichwortliste gelinkt ist
*)
VAR ptr : listWdwPtr;
BEGIN
IF handlePool.FindEntry(ADR(hdl), FindHandleCond, windows, ptr)
THEN
IF (ptr^.wdw >= 0)
THEN
v.bool := WdwManager.CloseWindow (ptr^.wdw, TRUE);
END;
END;
END listCloseByHandle;
PROCEDURE listUnlockWdw (hdl : LONGCARD);
VAR ptr : listWdwPtr;
BEGIN
IF handlePool.FindEntry(ADR(hdl), FindHandleCond, windows, ptr)
THEN
IF ptr^.usedByGrin > 0
THEN
DEC (ptr^.usedByGrin);
END;
IF ptr^.wdw >= 0
THEN
RETURN
ELSIF ptr^.usedByGrin = 0
THEN
freeList (ptr);
handlePool.FreeOneDataHandle(ptr^.grHandle);
handlePool.FreeOnePtr(ptr, windows);
END;
END;
END listUnlockWdw;
PROCEDURE listChangeGroup (hdl: LONGCARD; grinWdw: INTEGER; mess, newGroup: CARDINAL;
mode: grin.openMode): BOOLEAN;
VAR newPtr, ptr : listWdwPtr;
PROCEDURE openGroup (gruppe, which: CARDINAL; VAR ptr: listWdwPtr): BOOLEAN;
(* Ein Stichwortliste intern aufbauen ohne Fenster *)
VAR handlePtr : handlePool.oneHandlePtr;
i : CARDINAL;
varname : ARRAY [0..127] OF CHAR;
doRedraw : BOOLEAN;
BEGIN
(* Gruppe ffnen und Stichwortliste anzeigen *)
IF handlePool.BlankToList(ptr, TSIZE(listWindow), windows) THEN
IF handlePool.GetOneDatahandle(gruppe, handlePtr) THEN
ptr^.wdw := -1;
ptr^.grHandle := handlePtr;
ptr^.grinWindow := -1;
MakeTitle (gruppe, ptr^.grName);
ptr^.maxPos := data.LastMsgOfGroup (gruppe);
IF ptr^.maxPos = dataSys.empty
THEN
handlePool.FreeOneDataHandle(handlePtr);
handlePool.FreeOnePtr (ptr, windows);
RETURN FALSE
END;
IF which > ptr^.maxPos THEN which := ptr^.maxPos END;
ptr^.usedByGrin := 0;
(* Jetzt "Liste" aufbauen *)
ALLOCATE (ptr^.wholeList, LONG(ptr^.maxPos + 1) * LONG(TSIZE (listEntry)));
IF ptr^.wholeList # NIL THEN
ptr^.list := ptr^.wholeList;
(* Liste fllen *)
FOR i := 0 TO ptr^.maxPos DO
ptr^.wholeList^[i] := listEntry(lEntry{i, {}, NIL});
END;
IF gruppe = dataSys.private
THEN
ptr^.partArray := privateParts;
ELSE
ptr^.partArray := globalParts;
END;
ptr^.startPos := which;
ptr^.maxWidth := 0;
ptr^.isLocked := FALSE;
doRedraw := FALSE;
ptr^.unreadOrNew := (mode=grin.mFirstNew) OR (mode=grin.mUnread);
ptr^.openMode := mode;
(* Jetzt eventuell verkleinern *)
IF ptr^.unreadOrNew
THEN
ConfVars.GetConfDefBool (cListShrink, v.bool, FALSE);
IF v.bool
THEN
(* Liste verkleinern *)
shrinkToEnd (ptr, FALSE);
(* doRedraw := TRUE; *)
END;
(* Jetzt eventuell gefilterte rausnehmen *)
ConfVars.GetConfDefBool (cListFilter, v.bool, FALSE);
IF v.bool
THEN
(* Gefilterte selektieren und dann Liste verkleinern *)
listSelectFiltered (ptr^.wdw, TRUE, FALSE);
v.bool := shrinkList (ptr, TRUE, FALSE);
(* doRedraw := TRUE; *)
END;
(* Eventuellen Autoselect durchfhren *)
FOR i := 1 TO 10 DO
MagicStrings.Assign (cListSearch, varname);
MagicStrings.Append (StrConv.CardToStr (i, 0), varname);
ConfVars.GetConfDefBool (varname, v.bool, FALSE);
IF v.bool
THEN
(* Ok, steht auf TRUE, also selektieren *)
ptr^.isLocked := TRUE;
IF SearchHelp.getKonf (i-1, SearchHelp.suchVar)
& SearchHelp.ValidateKonf (SearchHelp.suchVar)
THEN
doMark (ptr, FALSE);
doRedraw := TRUE;
END;
ptr^.isLocked := FALSE;
END;
END;
(* Jetzt mal nachsehen, ob wir auch sortieren mssen *)
ConfVars.GetConfDefInt (cListSort, v.int, 3);
IF sortType(v.int) # sNum
THEN
ptr^.isLocked := TRUE;
doSort (ptr, sortType(v.int), FALSE);
doRedraw := TRUE;
ptr^.isLocked := FALSE;
END;
END;
IF doRedraw
THEN
WdwManager.FullRedrawWdw (ptr^.wdw);
END;
ELSE
handlePool.FreeOneDataHandle(handlePtr);
handlePool.FreeOnePtr (ptr, windows);
MTE.noMemAlert();
RETURN FALSE;
END;
ELSE
handlePool.FreeOnePtr (ptr, windows);
MTE.noMemAlert();
RETURN FALSE;
END;
ELSE
MTE.noMemAlert();
RETURN FALSE
END;
RETURN TRUE;
END openGroup;
BEGIN
IF handlePool.FindEntry(ADR(hdl), FindHandleCond, windows, ptr)
THEN
IF grinWdw # ptr^.grinWindow
THEN
RETURN FALSE;
END;
IF (ptr^.wdw >= 0) & openGroup (newGroup, mess, newPtr)
THEN
listUnlockWdw (hdl);
IF ptr^.usedByGrin = 0
THEN
WITH ptr^ DO
(* Speicher freigeben und Gruppe schlieen *)
freeList (ptr);
handlePool.FreeOneDataHandle(grHandle);
(* Jetzt neue Variablen berkopieren *)
wholeList:= newPtr^.wholeList;
list := newPtr^.list;
grHandle := newPtr^.grHandle;
grName := newPtr^.grName;
maxPos := newPtr^.maxPos;
startPos := newPtr^.startPos;
maxWidth := newPtr^.maxWidth;
partArray:= newPtr^.partArray;
(* neuen Ptr wieder freigeben *)
handlePool.FreeOnePtr (newPtr, windows);
newPtr := ptr;
END;
ELSE
(* Alte Gruppe ist mehrfach belegt, geht nicht. Neue wieder schlieen und
* alles freigeben
*)
freeList (newPtr);
handlePool.FreeOneDataHandle(newPtr^.grHandle);
handlePool.FreeOnePtr(newPtr, windows);
RETURN FALSE
END;
(* Nun auch dem Windowmanager ber die neuen Sachen informieren *)
WITH newPtr^ DO
(* grinWdw setzen *)
grinWindow := grinWdw;
(* Titel umsetzen *)
WdwManager.SetWdwTitle (wdw, grName);
(* Neue Dokumentparameter setzen *)
leftOffset := 0;
WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, TRUE);
END;
(* Und jetzt noch grin Bescheid sagen, da es ein neues Fenster gibt.
* Wichtig wegen der NextMessProzedur
*)
v.bool := grin.grinSetListWdw (newPtr^.grinWindow, grin.grinNextMess, LONGCARD (newPtr));
RETURN TRUE;
ELSE
listUnlockWdw (hdl); (* mu gemacht werden *)
RETURN FALSE (* Gruppe konnte nicht geffnet werden *)
END;
ELSE
RETURN FALSE;
END;
END listChangeGroup;
PROCEDURE listSearch (wdw: INTEGER);
(* Nachrichten werden ber die Suchfunktion markiert
*)
VAR ptr: listWdwPtr;
BEGIN
IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr)
THEN
doMark (ptr, TRUE);
END;
END listSearch;
PROCEDURE parseListLine (REF listline : ARRAY OF CHAR; private : BOOLEAN; onlyTest : BOOLEAN) : BOOLEAN;
TYPE charSet = SET OF CHAR;
CONST okSet = charSet{'A','C', 'D', 'E', 'F', 'H', 'I', 'L', 'M', 'R' , 'S', 'U', 'W', '#', ',', ' '};
numSet = charSet{'0'..'9'};
skipSet = charSet{' ',','};
formatSet = charSet{'B','D','H','T'};
VAR p : partArrayDesc;
num : LONGCARD;
ch : CHAR;
z, l: CARDINAL;
pName : partNameType;
fStr : partFormat;
i : INTEGER;
BEGIN
l := LENGTH (listline);
IF l = 0 THEN RETURN FALSE END;
z := 0;
p.lines := 0;
p.width := 0;
WHILE z < l DO
(* Ersten Eintrag suchen *)
WHILE (z < l) & (listline[z] IN skipSet) DO INC (z) END;
IF z < l
THEN
ch := listline[z];
FOR i := 0 TO partFormatLength-1 DO fStr[i] := 0C; END;
IF (listline[z+1] # '(') THEN RETURN FALSE END;
INC (z,2); (* z+1 = '(' *)
num := 0;
WHILE (listline [z] IN numSet) & (z < l) DO num := num * 10 + LONG(ORD (listline[z]) - ORD('0')); INC(z); END;
IF (z >= l) OR
( (listline[z] # ')') &
( (listline[z] # ',') & ~(ch IN formatSet))
)
THEN
RETURN FALSE
END;
IF (listline[z] = ',') & (ch IN formatSet)
THEN
(* Formatstring lesen *)
INC (z); (* ',' berspringen *)
i := 0;
WHILE (listline[z] # ')') & (z < l) & (i < partFormatLength) DO
fStr[i] := listline[z];
INC (z); INC (i);
END;
IF (i >= partFormatLength) OR (z >= l) THEN RETURN FALSE END;
END;
INC(z); (* ')' berspringen *)
CASE ch OF
'A' : pName := pRealName |
'B' : pName := pWeekday;
IF fStr[0] = ''
THEN
Strings.Assign ('GGGGGGGGGGG', fStr, v.bool);
ELSIF (fStr[0] = '#') & (fStr[1] # '')
THEN
ch := fStr[1];
FOR i := 0 TO partFormatLength DO
fStr[i] := ch;
END;
END; |
'C' : pName := pComments |
'D' : pName := pDatum;
IF fStr[0] = ''
THEN
Strings.Assign ('DD.MM.YY', fStr, v.bool);
END; |
'E' : pName := pOwnMess |
'F' : pName := pFlags |
'H' : pName := pFuzzytime;
IF fStr[0] = ''
THEN
Strings.Assign ('G', fStr, v.bool);
END; |
'L' : pName := pLength |
'M' : pName := pMailId |
'I' : pName := pMId |
'R' : pName := pRefId |
'S' : pName := pStatus |
'T' : pName := pTime;
IF fStr[0] = ''
THEN
Strings.Assign ('HH:MM', fStr, v.bool);
END; |
'U' : pName := pUserName |
'W' : pName := pWegen |
'#' : pName := pCount |
ELSE
RETURN FALSE;
END;
IF (num = 0) OR (num > 1024) THEN RETURN FALSE END;
p.parts[p.lines] := partType{pName, INTEGER(SHORT(num)), fStr};
INC (p.lines);
INC (p.width, num);
END;
END;
IF p.lines = 0
THEN
RETURN FALSE
END;
IF onlyTest THEN RETURN TRUE END;
IF private
THEN
v.bool := ConfVars.SetConfigString (cPrivateLine, listline);
privateParts := p;
ELSE
v.bool := ConfVars.SetConfigString (cGlobalLine, listline);
globalParts := p;
END;
RETURN TRUE;
END parseListLine;
PROCEDURE CheckListLine (REF listline : ARRAY OF CHAR): BOOLEAN;
(* Testet, ob die bergebene Zeile fr die Stichwortliste in Ordnung ist *)
(* Das Format einer Zeile besteht aus einzelnen Krzeln
* fr einen Eintrag und darauffolgend in Klammern die Weite dieses Eintrages.
* Beispiel: D(12),I(10),U(30),W(30),F(2)
* Erlaubte Zeilenelemente:
* D: Datum. Das Datum ist maximal 12 Zeichen lang und hat folgende Form:
* Mo, 16.11.92
* Optional kann man auch einen Formatstring angeben, der folgende Elemente
* enthalten darf:
* D: Tagesziffer (d: wird gelscht, wenn nicht auffllbar)
* Y: Jahresziffer (y: wird gelscht, wenn nicht auffllbar)
* M: Monatsziffer (m: wird gelscht, wenn nicht auffllbar)
* G: Monatsbuchstabe Deutsch
* F: Monatsbuchstabe Frnzsisch
* E: Monatsbuchstabe English
* #E (Hinter Ziffern): englische Zahlfortsetzung (1st, 2nd, 3rd, 4th...)
* T: Zeit. Default-Format fr die Zeit ist HH:SS, also 06:13.
* Optional kann man auch einen Formatstring angeben, der folgendes
* enthalten darf:
*
* HH: Stundenzahl ("hh" lscht fhrende Null)
* MM: Minutenzahl ("mm" lscht fhrende Null)
* SS: Sekundenzahl ("ss" lscht fhrende Null)
*
* #E: AM/PM-Notierung (English) ("e" schreibt "am" bzw. "pm")
*
* Beispiel: Aus 'hh Uhr mm' wird '13 Uhr 5'
* Die Angabe von Sekunden in einem Formatstring ist allerdings unsinnig,
* da die Zeitangaben zu Mails keine Sekunden enthalten.
* W: Wochentag. Auch hier kann man einen Formatstring angeben, der die Sprache
* spezifiziert, in der der Wochentag ausgegeben wird.
*
* G: Tagesbuchstabe Deutsch
* F: Tagesbuchstabe Frnzsisch
* E: Tagesbuchstabe English
*
* Es mu fr die gesamte gewnschte Lnge ein Formatbuchstabe angegeben
* werden.
* Wenn das erste Zeichen in der Maske ein # ist, dann wird die
* Maske komplett mit dem zweiten Zeichen der Maske gefllt.
* Beispiel: Aus #G wird intern GGGGGGGGGGGGGG
*
* I: Message-Id. Im Moment ist diese maximal 10 Zeichen lang, aber ab Maus 9.0
* knnen Ids wesentlich lnger werden.
* R: Reference-Id: Bei Kommentaren oder Antworten die Id der Referenznachricht.
* U: Username
* A: Realname (wird ersetzt durch Username, falls nicht vorhanden)
* W: Stichwort. Vor MAUS 9 maximal 30 Zeichen.
* F: Flags. Die Flags der Nachrichten, die man in CAT setzen kann.
* Reihenfolge wie in der Messageanzeige, also LFITDKB12
* S: Status. Nur fr persnliche Nachrichten, andernfalls wird es ignoriert.
* C: Kommentare: Anzahl der Kommentare auf die Nachricht, nicht fr persnliche Nachrichten.
* #: interne Nummer der Message. Maximal 5 Stellen.
*)
BEGIN
RETURN parseListLine (listline, FALSE, TRUE);
END CheckListLine;
PROCEDURE SetListLine (REF listline : ARRAY OF CHAR; private : BOOLEAN);
(* Setzt die Stichwortlistenzeile fr die private oder andere Gruppen
* Wenn die Zeile fehlerhaft ist, wird die vorhandene Zeile nicht
* verndert.
*)
BEGIN
v.bool := parseListLine (listline, private, FALSE);
END SetListLine;
VAR init: BOOLEAN;
PROCEDURE InitMsgList ();
(* Initialisiert die Messageliste *)
BEGIN
IF ~init THEN
butBox := MausTauschrsc.TreeAddr^[MausTauschrsc.listctl];
v.bool := mtXobjects.InstUserdef (butBox, MausTauschrsc.listread, mtDials.DrawButton, NIL);
selPop := MausTauschrsc.TreeAddr^[MausTauschrsc.lselpop];
removePop := MausTauschrsc.TreeAddr^[MausTauschrsc.lremvpop];
sortPop := MausTauschrsc.TreeAddr^[MausTauschrsc.lsortpop];
END;
init := TRUE;
END InitMsgList;
BEGIN
Lists.CreateList (windows, v.bool);
(*
privateParts.parts[0] := partType{pDatum, 12, ''};
privateParts.parts[1] := partType{pMailId, 10, ''};
privateParts.parts[2] := partType{pUserName, 30, ''};
privateParts.parts[3] := partType{pWegen, 30, ''};
privateParts.parts[4] := partType{pStatus, 2, ''};
privateParts.width := 84;
privateParts.lines := 5;
globalParts := privateParts;
globalParts.parts[5] := globalParts.parts[4];
globalParts.parts[4] := partType{pComments, 2};
globalParts.width := 86;
globalParts.lines := 6;
*)
globalNumber := -1;
lineDist := 2;
pixOffset := 8;
init := FALSE;
lastSaveMode := 1;
extendedCommentMode := TRUE;
END msgList.